﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zcu.PanelComposer.ViewModels.Core;
using System.ComponentModel.Composition;
using Zcu.PanelComposer.Interfaces;
using Caliburn.Micro;
using Zcu.PanelComposer.ViewModels.Events;
using Zcu.PanelComposer.Models.Model;
using System.Windows.Media.Media3D;
using System.Windows.Media;
using System.ComponentModel;
using System.Windows.Threading;

namespace Zcu.PanelComposer.ViewModels.Pages
{
    /// <summary>
    /// Vazby mezi solution a projekty.
    /// </summary>
    [Export(typeof(IModule))]
    public class SolutionProjectsViewModel : NavigateScreen, IHandle<ActiveSolutionEvent>
    {
        #region Fields

        /// <summary>
        /// Reference na logger.
        /// </summary>
        private readonly ILog _log = LogManager.GetLog(typeof(SolutionProjectsViewModel));

        private Solution _SelectedSolution;
        private BindableCollection<SolutionProject> _SolutionProject;
        private SolutionProject _SelectedSolutionProject;

        private Model3D _Model;

        #endregion

        #region Properties

        /// <summary>
        /// Pristup na databazi.
        /// </summary>
        [Import]
        public IRepository Repository { get; private set; }

        /// <summary>
        /// Gets or sets the model.
        /// </summary>
        /// <value>
        /// The model.
        /// </value>
        public Model3D Model
        {
            get { return _Model; }
            set
            {
                if (_Model != value) _Model = value;
                NotifyOfPropertyChange(() => Model);
            }
        }

        /// <summary>
        /// Gets or sets the selected solution.
        /// </summary>
        /// <value>
        /// The selected solution.
        /// </value>
        public Solution SelectedSolution
        {
            get { return _SelectedSolution; }
            set
            {
                if (_SelectedSolution != value) _SelectedSolution = value;
                NotifyOfPropertyChange(() => SelectedSolution);
            }
        }

        /// <summary>
        /// Gets or sets the project.
        /// </summary>
        /// <value>
        /// The project.
        /// </value>
        public BindableCollection<SolutionProject> SolutionProject
        {
            get { return _SolutionProject; }
            set
            {
                if (_SolutionProject != value) _SolutionProject = value;
                NotifyOfPropertyChange(() => SolutionProject);
            }
        }

        /// <summary>
        /// Gets or sets the selected project.
        /// </summary>
        /// <value>
        /// The selected project.
        /// </value>
        public SolutionProject SelectedSolutionProject
        {
            get { return _SelectedSolutionProject; }
            set
            {
                if (_SelectedSolutionProject != value) _SelectedSolutionProject = value;
                NotifyOfPropertyChange(() => SelectedSolutionProject);

                NotifyOfPropertyChange(() => CanActiveProjectAction);
                NotifyOfPropertyChange(() => CanDeleteSolutionProjectAction);
                NotifyOfPropertyChange(() => CanEditSolutionProjectAction);
            }
        }

        #endregion

        #region Guard methods

        /// <summary>
        /// Gets a value indicating whether this instance can active project.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance can active project; otherwise, <c>false</c>.
        /// </value>
        public bool CanActiveProjectAction { get { return SelectedSolutionProject != null; } }

        /// <summary>
        /// Gets a value indicating whether this instance can edit solution project action.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance can edit solution project action; otherwise, <c>false</c>.
        /// </value>
        public bool CanEditSolutionProjectAction { get { return SelectedSolutionProject != null; } }

        /// <summary>
        /// Gets a value indicating whether this instance can delete solution project.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance can delete solution project; otherwise, <c>false</c>.
        /// </value>
        public bool CanDeleteSolutionProjectAction { get { return SelectedSolutionProject != null; } }



        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="SolutionProjectsViewModel"/> class.
        /// </summary>
        public SolutionProjectsViewModel()
        {
            /// todo do resources
            DisplayName = "Projects overview for solution";
            ModuleName = PageNames.SolutionProjects;
            Order = 4;
            MenuVisible = false;
        }

        #endregion

        #region Overrided methods

        /// <summary>
        /// Udalost, ktera je volana hned po vytvoreni screenu.
        /// </summary>
        public override void OnReconstruct()
        {
            base.OnReconstruct();

            // registrace zachycovani udalosti zmeny projektu.
            EventAggregator.Subscribe(this);
        }

        /// <summary>
        /// Called when activating.
        /// </summary>
        protected override void OnActivate()
        {
            base.OnActivate();

            // nacteni dat
            LoadData();

            // vytvor 3D model
            Create3DModel();
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Actives the project action.
        /// </summary>
        public void ActiveProjectAction()
        {
            EventAggregator.Publish(new ActiveProjectEvent(SelectedSolutionProject.Project));
            Navigate(PageNames.ProjectDetail);
        }

        /// <summary>
        /// Edits the solution project action.
        /// </summary>
        public void EditSolutionProjectAction()
        {
            Navigate(PageNames.NewSolutionProject, SelectedSolutionProject);
        }

        /// <summary>
        /// News the solution project action.
        /// </summary>
        public void NewSolutionProjectAction()
        {
            Navigate(PageNames.NewSolutionProject);
        }

        /// <summary>
        /// Deletes the solution project action.
        /// </summary>
        public void DeleteSolutionProjectAction()
        {
            // smazeme
            Repository.Delete<SolutionProject>(SelectedSolutionProject);
            Repository.Commit();

            // nacteme
            LoadData();
        }

        #endregion

        #region Handle methods

        /// <summary>
        /// Handles the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Handle(ActiveSolutionEvent message)
        {
            _log.Info("Handle event {0}", message);
            SelectedSolution = (Solution)message.Solution;

        }

        #endregion

        #region Private methods

        /// <summary>
        /// Create 3D model.
        /// </summary>
        private void Create3DModel()
        {
            Model3DGroup group = new Model3DGroup();
            string path = string.Empty;

            var solutionProjects = Repository.GetAll<SolutionProject>(s => s.Solution == SelectedSolution);

            foreach (var solutionProject in solutionProjects)
            {
                var project = solutionProject.Project;

                // kontrola, zdali project obsahuje vse pro vygenerovani 3D Modelu
                if (!string.IsNullOrEmpty(project.BasePolygon)
                    && !string.IsNullOrEmpty(project.XamlTexture))
                {
                    // model
                    Model3D model = null;
                    // path = FileHelper.GetDrawingPath(project.Drawing);

                    // vytvorime kolekci bodu
                    var poly = PointCollection.Parse(project.BasePolygon);
                    // vytvorime instanci pomocne tridy generujici 3D model
                    Polygon3DModel pModel = new Polygon3DModel(poly);
                    // vygenerujeme model
                    model = pModel.CreateModel(project.Floors * 50, Utils.DeserializableCanvas(project.XamlTexture));

                    // transformace
                    var transformGroup = new Transform3DGroup();
                    transformGroup.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), 180 - solutionProject.Angle_Rotation)));
                    transformGroup.Children.Add(new TranslateTransform3D(solutionProject.X_Translate, solutionProject.Y_Translate, solutionProject.Z_Translate));
                    model.Transform = transformGroup;

                    // pridani modelu do groupy
                    group.Children.Add(model);
                }
            }

            // predame groupu
            Model = group;
        }

        /// <summary>
        /// Loads the data.
        /// </summary>
        private void LoadData()
        {
            SolutionProject = new BindableCollection<SolutionProject>(
                Repository.GetAll<SolutionProject>(s => s.Solution == SelectedSolution)
                );
        }

        #endregion
    }
}
